![うっかりrdsproxyadminから権限を剥奪してもRDS Proxyが正常動作するのか確認してみた](https://devio2023-media.developers.io/wp-content/uploads/2019/05/amazon-rds.png)
うっかりrdsproxyadminから権限を剥奪してもRDS Proxyが正常動作するのか確認してみた
MAD事業部@大阪の岩田です。
先日こんなブログを書きました。
rdsproxyadmin
のパスワードを手動変更してもRDS Proxyの基盤側でパスワードが再設定され、自動復旧することが確認できました。ここで新たな疑問が湧いてきました。rdsproxyadmin
からRDS Proxyの正常動作に必要な権限を剥奪するとどうなるのでしょうか?同じように自動復旧してくれるのでしょうか?気になったので検証してみました。
環境
今回利用したRDSの環境です
- RDS for PostgreSQL
- エンジンバージョン 13.6
- インスタンスクラス db.t3.micro
やってみる
軽く事前準備と確認
前回のブログと同様にRDS & RDS Proxyの環境を構築して簡単なSQLの発行まで試しておきます。
適当なEC2からpsqlでRDS Proxy経由でRDSに接続してクエリを発行してみます
$ psql -h <RDSプロキシのエンドポイント> -U user01 db1 Password for user user01: psql (13.3, server 13.4) SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off) Type "help" for help. db1=> select now(); now ------------------------------- 2022-06-13 01:01:12.567261+00 (1 row) db1=>
OKです。
RDSに直接接続したpsqlのセッションからRDS <-> RDS Proxy間の接続をクローズしておきます。
postgres=> select pid from pg_stat_activity where usename = 'user01'; pid ------- 24906 (1 rows) postgres=> select pg_terminate_backend(24906); pg_terminate_backend ---------------------- t (1 row) postgres=> select pid from pg_stat_activity where usename = 'user01'; pid ----- (0 rows)
rdsproxyadminからCONNECT権限をREVOKEしてみる
ウォームアップが完了したので、ここからがRDSのマスターユーザーを使ってrdsproxyadmin
かCONNECT権限をREVOKEしていきます。
CONNECT権限はpublicロールに付与されているので、publicロールからCONNECT権限をREVOKEする形になります。事前に通常のユーザーセッションで利用するDBユーザーにCONNECT権限を付与しておきます。
postgres=> grant connect on database db1 to user01;
ではpublicロールからCONNECT権限をREVOKEしてみましょう。RDSに直接接続しているpsqlセッションから以下のSQLを発行します。
postgres=> revoke connect on database postgres from public; REVOKE
これでpublicロールからCONNECT権限が剥奪され、rdsproxyadmin
もCONNECT権限がなくなったはずです。すでに接続済のrdsproxyadmin
のセッションをすべてCLOSEします、
postgres=> select 'select pg_terminate_backend(' || pid || ');' from pg_stat_activity where usename = 'rdsproxyadmin'; ?column? ------------------------------------ select pg_terminate_backend(5267); select pg_terminate_backend(5268); (2 rows) postgres=> select pg_terminate_backend(5267); pg_terminate_backend ---------------------- t (1 row) postgres=> select pg_terminate_backend(5268); pg_terminate_backend ---------------------- t (1 row)
準備が整ったので、EC2からRDS Proxyに接続してSQLを発行してみましょう
$ psql -h pg13proxy.proxy-czo4ezbcwzku.ap-northeast-1.rds.amazonaws.com -U user01 db1 Password for user user01: psql (13.3, server 13.4) SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off) Type "help" for help. db1=> select now(); now ------------------------------- 2022-06-13 01:51:26.241751+00 (1 row)
普通に成功してしまいました。pg_stat_activityの状況を確認してみます。
postgres=> select usename,count(*) from pg_stat_activity group by usename; usename | count ---------------+------- | 4 user01 | 2 rdsproxyadmin | 2 postgres | 1 rdsadmin | 2 (5 rows) postgres=>
普通にrdsproxyadminのセッションが存在します。ログはどうでしょうか?まずRDS側のログです。
2022-06-13 01:46:29 UTC:172.31.9.117(42252):postgres@postgres:[698]:LOG: statement: revoke connect on database db1 from public; 2022-06-13 01:46:30 UTC:172.31.59.48(37801):rdsproxyadmin@postgres:[5268]:LOG: statement: SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH F ROM now() - pg_postmaster_start_time()) AS uptime; ...略 2022-06-13 01:51:08 UTC:172.31.9.117(42252):postgres@postgres:[698]:LOG: statement: select pg_terminate_backend(5268); 2022-06-13 01:51:08 UTC:172.31.59.48(37801):rdsproxyadmin@postgres:[5268]:FATAL: terminating connection due to administrator command 2022-06-13 01:51:08 UTC:172.31.30.94(33351):[unknown]@[unknown]:[26256]:LOG: connection received: host=172.31.30.94 port=33351 2022-06-13 01:51:08 UTC:172.31.30.94(33351):rdsproxyadmin@postgres:[26256]:LOG: connection authorized: user=rdsproxyadmin database=postgres 2022-06-13 01:51:08 UTC:172.31.30.94(33351):rdsproxyadmin@postgres:[26256]:LOG: statement: SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime; 2022-06-13 01:51:09 UTC:172.31.59.48(36381):[unknown]@[unknown]:[26257]:LOG: connection received: host=172.31.59.48 port=36381 2022-06-13 01:51:09 UTC:172.31.59.48(36381):rdsproxyadmin@postgres:[26257]:LOG: connection authorized: user=rdsproxyadmin database=postgres 2022-06-13 01:51:09 UTC:172.31.59.48(36381):rdsproxyadmin@postgres:[26257]:LOG: statement: SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime; 2022-06-13 01:51:09 UTC:172.31.30.94(33351):rdsproxyadmin@postgres:[26256]:LOG: statement: SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime;
普通にREVOKE完了後にも接続成功のログが上がってきています。特にRDS Proxyの基板側でGRANTし直したということも無いようです。
RDS Proxy側のログはどうでしょうか?
@timestamp | @message |
---|---|
2022-06-13 01:51:14.434 | 2022-06-13T01:51:09.113Z [INFO] Database "pg13" at 172.31.20.74:5432 is now available for read/write access from 172.31.59.48. |
2022-06-13 01:51:14.790 | 2022-06-13T01:51:08.796Z [INFO] Database "pg13" at 172.31.20.74:5432 is now available for read/write access from 172.31.30.94. |
2022-06-13 01:51:20.915 | 2022-06-13T01:51:20.817Z [INFO] [proxyEndpoint=default] [clientConnection=256173523] A new client connected from 172.31.9.117:55630. |
2022-06-13 01:51:23.417 | 2022-06-13T01:51:20.836Z [DEBUG] [proxyEndpoint=default] [clientConnection=256173523] Received Startup Message: [username="user01", database="db1", protocolMajorVersion=3, protocolMinorVersion=0, sslEnabled=true] |
2022-06-13 01:51:23.417 | 2022-06-13T01:51:23.218Z [INFO] [proxyEndpoint=default] [clientConnection=4153722911] A new client connected from 172.31.9.117:42404. |
2022-06-13 01:51:23.417 | 2022-06-13T01:51:23.232Z [DEBUG] [proxyEndpoint=default] [clientConnection=4153722911] Received Startup Message: [username="user01", database="db1", protocolMajorVersion=3, protocolMinorVersion=0, sslEnabled=true] |
2022-06-13 01:51:26.419 | 2022-06-13T01:51:23.235Z [DEBUG] [proxyEndpoint=default] [clientConnection=4153722911] Proxy authentication with PostgreSQL native password authentication succeeded for user "user01" with TLS on. |
2022-06-13 01:51:26.419 | 2022-06-13T01:51:26.225Z [INFO] [dbConnection=1921691738] A TCP connection was established from the proxy at 172.31.30.94:7547 to the database at 172.31.20.74:5432. |
2022-06-13 01:51:26.419 | 2022-06-13T01:51:26.241Z [DEBUG] [dbConnection=1921691738] The new database connection successfully authenticated with TLS on. |
2022-06-13 01:51:26.419 | 2022-06-13T01:51:26.241Z [DEBUG] [proxyEndpoint=default] [clientConnection=4153722911] The client connection borrowed the database connection [dbConnection=1921691738] for the next query/transaction. |
2022-06-13 01:51:31.791 | 2022-06-13T01:51:26.242Z [DEBUG] [proxyEndpoint=default] [clientConnection=4153722911] The database connection [dbConnection=1921691738] borrowed from the connection pool is being released to the connection pool. |
こちらも特にrdsproxyadminの接続が失敗したといったログは見当たりませんでした。rdsproxyadmin
ロールの設定を見る限りpublic以外のロール(グループ)に所属しているということも無さそうですが、なぜCONNECTできたのかよく分かりませんでした...うーむ。。
List of roles Role name | Attributes | Member of -----------------+------------------------------------------------------------+------------------------------------------------------------- postgres | Create role, Create DB +| {rds_superuser} | Password valid until infinity | rds_ad | Cannot login | {} rds_iam | Cannot login | {} rds_password | Cannot login | {} rds_replication | Cannot login | {} rds_superuser | Cannot login | {pg_monitor,pg_signal_backend,rds_replication,rds_password} rdsadmin | Superuser, Create role, Create DB, Replication, Bypass RLS+| {} | Password valid until infinity | rdsproxyadmin | Password valid until infinity | {} rdsrepladmin | No inheritance, Cannot login, Replication | {} rdstopmgr | Password valid until infinity | {pg_monitor} user01 | Create DB | {}
rdsproxyadminロールの属性をNOLOGINに変更してみる
SELECT権限のREVOKEでは予想に反してダウンタイムが発生しませんでした。今度はrdsproxyadminロールの属性をNOLOGINに変更するとどうなるかを確認してみます。
postgres=> alter role rdsproxyadmin with nologin; ALTER ROLE postgres=>
すでに接続済のrdsproxyadmin
のセッションをすべてCLOSEします、
postgres=> select 'select pg_terminate_backend(' || pid || ');' from pg_stat_activity where usename = 'rdsproxyadmin'; ?column? ------------------------------------- select pg_terminate_backend(26256); select pg_terminate_backend(26257); (2 rows) postgres=> select pg_terminate_backend(26256); pg_terminate_backend ---------------------- t (1 row) postgres=> select pg_terminate_backend(26257); pg_terminate_backend ---------------------- t (1 row)
EC2からpsqlでRDS Proxyに接続し、SQLの発行を試みます
$ psql -h <RDS Proxyのエンドポイント> -U user01 db1 Password for user user01: psql (13.3, server 13.4) SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off) Type "help" for help. db1=> select now(); ERROR: Timed-out waiting to acquire database connection.
select now()
実行後にレスポンスが返却されず固まり、その後エラーが返却されました。待ち時間はきちんと計測した訳ではありませんが、体感としてはRDS Proxyの「接続借用タイムアウト」で指定された2分程度だった印象です。
RDSのログを確認してみましょう
2022-06-13 02:13:45 UTC:172.31.9.117(42252):postgres@postgres:[698]:LOG: statement: alter role rdsproxyadmin with nologin; 2022-06-13 02:13:45 UTC:172.31.59.48(36381):rdsproxyadmin@postgres:[26257]:LOG: statement: SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime; ...略 2022-06-13 02:14:03 UTC:172.31.9.117(42252):postgres@postgres:[698]:LOG: statement: select pg_terminate_backend(26257); 2022-06-13 02:14:03 UTC:172.31.59.48(36381):rdsproxyadmin@postgres:[26257]:FATAL: terminating connection due to administrator command 2022-06-13 02:14:03 UTC:172.31.30.94(38231):[unknown]@[unknown]:[8749]:LOG: connection received: host=172.31.30.94 port=38231 2022-06-13 02:14:03 UTC:172.31.30.94(38231):rdsproxyadmin@postgres:[8749]:LOG: connection authorized: user=rdsproxyadmin database=postgres 2022-06-13 02:14:03 UTC:172.31.30.94(38231):rdsproxyadmin@postgres:[8749]:FATAL: role "rdsproxyadmin" is not permitted to log in 2022-06-13 02:14:03 UTC:172.31.59.48(44961):[unknown]@[unknown]:[8752]:LOG: connection received: host=172.31.59.48 port=44961 2022-06-13 02:14:03 UTC:172.31.59.48(44961):rdsproxyadmin@postgres:[8752]:LOG: connection authorized: user=rdsproxyadmin database=postgres 2022-06-13 02:14:03 UTC:172.31.59.48(44961):rdsproxyadmin@postgres:[8752]:FATAL: role "rdsproxyadmin" is not permitted to log in 2022-06-13 02:14:04 UTC:172.31.30.94(52035):[unknown]@[unknown]:[8756]:LOG: connection received: host=172.31.30.94 port=52035 2022-06-13 02:14:04 UTC:172.31.30.94(52035):rdsproxyadmin@postgres:[8756]:LOG: connection authorized: user=rdsproxyadmin database=postgres 2022-06-13 02:14:04 UTC:172.31.30.94(52035):rdsproxyadmin@postgres:[8756]:FATAL: role "rdsproxyadmin" is not permitted to log in
権限不足によるエラーログが大量出力されています。
RDS Proxy側のログはどうでしょうか?
@timestamp | @message |
---|---|
2022-06-13 02:14:14.957 | 2022-06-13T02:14:14.709Z [INFO] [proxyEndpoint=default] [clientConnection=2841168921] A new client connected from 172.31.9.117:55652. |
2022-06-13 02:14:19.011 | 2022-06-13T02:14:18.842Z [INFO] [proxyEndpoint=default] [clientConnection=42225156] A new client connected from 172.31.9.117:42426. |
2022-06-13 02:14:19.011 | 2022-06-13T02:14:18.856Z [DEBUG] [proxyEndpoint=default] [clientConnection=42225156] Received Startup Message: [username="user01", database="db1", protocolMajorVersion=3, protocolMinorVersion=0, sslEnabled=true] |
2022-06-13 02:14:20.434 | 2022-06-13T02:14:14.758Z [DEBUG] [proxyEndpoint=default] [clientConnection=2841168921] Received Startup Message: [username="user01", database="db1", protocolMajorVersion=3, protocolMinorVersion=0, sslEnabled=true] |
2022-06-13 02:14:24.791 | 2022-06-13T02:14:18.858Z [DEBUG] [proxyEndpoint=default] [clientConnection=42225156] Proxy authentication with PostgreSQL native password authentication succeeded for user "user01" with TLS on. |
こちらはpsql <-> RDS Proxy間の接続・認証成功などのログは出力されていますが、RDS Proxy<->RDS間の接続エラーに関するログは特に出力されていないようです。
ちなみにマネコンの表示もステータス:使用不可
に変わっていました。
その後1時間ほど放置していましたが、rdsproxyadmin
のパスワード変更時とは違って特に自動復旧はしませんでした。
まとめ
うっかりrdsproxyadmin
ロールの属性をNOLOGINに変更するとRDS Proxyが正常利用できなくなってしまうようです。基盤側でうまく自動復旧してくれるといったことも無い様なので気を付けましょう。
この記事が誰の役にも立たないことを願います。